package com.xframe.xdal.core.model.sqlbuilder.proc;

import com.xframe.xdal.core.constant.DalConstants;
import com.xframe.xdal.core.model.SetWrap;
import com.xframe.xdal.core.model.UpdateAttr;
import com.xframe.xdal.core.model.UpdateSetWrap;
import com.xframe.xdal.core.model.mapping.IColumnMapping;
import com.xframe.xdal.core.model.mapping.ITableInfo;
import com.xframe.xdal.core.model.sqlbuilder.BaseSqlBuilder;
import com.xframe.xdal.core.model.sqlbuilder.BuilderContext;
import com.xframe.xdal.core.model.sqlbuilder.DbExpression;
import com.xframe.xdal.core.model.sqlbuilder.SqlExpression;

import java.util.ArrayList;
import java.util.List;

/**
 * 功能描述：根据UpdateAtt来构造更新sql语句
 * 创建人：xufeng
 * 创建时间：2022/10/8 10:04
 *
 * @version 1.0
 **/
public class DefUpdateSqlBuilder extends BaseSqlBuilder {

    /**
     * 更新sql 语句
     *
     * @return sql 语句
     */
    public String getSQL() {
        return " update %s set %s where %s ";
    }

    /**
     * 根据UpdateAtt来构造更新sql语句
     *
     * @param context
     * @return
     */
    @Override
    public SqlExpression build(BuilderContext context) {
        ITableInfo tableInfo = context.getTableInfo();


        UpdateAttr updateAttr = context.getUpdateAttr();
        List<IColumnMapping> columnMappingList = updateAttr.getSetColumnMappingList(tableInfo);
        List<IColumnMapping> whereColumnMappingList = updateAttr.getWhereColumnMappingList(tableInfo);
        // 参数list
        List<Object> paramList = new ArrayList<>();
        StringBuilder setStrBuilder = new StringBuilder();
        buildSetSql(columnMappingList,setStrBuilder,context,paramList);
        if(updateAttr.isVerFlag()) {
            IColumnMapping verColumnMapping = context.findVer();
            setStrBuilder.append(DalConstants.SQL_SEPARATION);
            setStrBuilder.append(context.getNameConvert().toName(verColumnMapping.getName()) +
                    DalConstants.SQL_EQUAL + context.getNameConvert().toName(verColumnMapping.getName()) + " + 1");
        }

        StringBuilder whereStrBuilder = new StringBuilder();
        buildWhereSql(whereColumnMappingList,whereStrBuilder,context,paramList);


        String updateSql = String.format(getSQL(), context.getNameConvert().toName(tableInfo.getName()), setStrBuilder, whereStrBuilder);
        return new SqlExpression(updateSql, paramList,context.getDataSourceTypeEnums());
    }


    /**
     * 构造set字段builder
     *
     * @param columnMappingList  字段李斯特
     * @param stringBuilder builder
     * @param context       上下文
     * @param paramList     参数list
     */
    private void buildSetSql(List<IColumnMapping> columnMappingList,StringBuilder stringBuilder,
                             BuilderContext context, List<Object> paramList){
        UpdateAttr updateAttr = context.getUpdateAttr();
        for(int index = 0; index < columnMappingList.size(); index++){
            IColumnMapping columnMapping = columnMappingList.get(index);

            stringBuilder.append(context.getNameConvert().toName(columnMapping.getName()));
            stringBuilder.append(DalConstants.SQL_EQUAL);
            if (columnMapping.getUseDbObjectFlag()) {
                String dbExp = DbExpression.getDbExpression().getExpression(columnMapping.getDbExpression(), context.getDataSourceTypeEnums());
                stringBuilder.append(dbExp);
            } else {
                UpdateSetWrap updateSetWrap = updateAttr.getUpdateSetWrap(columnMapping.getFieldName());
                switch (updateSetWrap.getMode()) {
                    case AUTOINCREMENT:
                        stringBuilder.append(context.getNameConvert().toName(columnMapping.getName()));
                        stringBuilder.append(DalConstants.SQL_ADD);
                        stringBuilder.append(DalConstants.SQL_PLACE_HOlDER);
                        paramList.add(context.getData().getObjectFieldValue(columnMapping.getFieldName()));
                        break;
                    case DECREMENT:
                        stringBuilder.append(context.getNameConvert().toName(columnMapping.getName()));
                        stringBuilder.append(DalConstants.SQL_SUB);
                        stringBuilder.append(DalConstants.SQL_PLACE_HOlDER);
                        paramList.add(context.getData().getObjectFieldValue(columnMapping.getFieldName()));
                        break;
                    case KEYVALUE:
                    default:
                        stringBuilder.append(DalConstants.SQL_PLACE_HOlDER);
                        paramList.add(context.getData().getObjectFieldValue(columnMapping.getFieldName()));
                        break;
                }

            }
            if(index + 1 < columnMappingList.size()) {
                stringBuilder.append(DalConstants.SQL_SEPARATION);
            }

        }
    }


    private void buildWhereSql(List<IColumnMapping> columnMappingList,StringBuilder stringBuilder,
                               BuilderContext context, List<Object> paramList){
        boolean isFirst = true;
        for(IColumnMapping columnMapping : columnMappingList){
            if(!isFirst){
                stringBuilder.append(DalConstants.SQL_AND);
            }
            isFirst = false;
            stringBuilder.append(context.getNameConvert().toName(columnMapping.getName()));
            stringBuilder.append(DalConstants.SQL_EQUAL);
            stringBuilder.append(DalConstants.SQL_PLACE_HOlDER);
            paramList.add(context.getData().getObjectFieldValue(columnMapping.getFieldName()));
        }

    }
}
